package com.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateUtils;
import org.joda.time.DateTime;
import org.joda.time.Days;
import org.joda.time.LocalDateTime;
import org.joda.time.format.DateTimeFormat;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.Date;

/**
 * @author zhangbao
 * @date 2022/10/1
 */
@Slf4j
public class DateUtil {

    public static final String DATE_PATTERN = "yyyy-MM-dd";
    public static final String DEFAULT_PATTERN = "yyyy-MM-dd HH:mm:ss";
    public static final String YYYY_MM = "yyyy-MM";
    public static final String YYYY_MM_DD_WITH_NOT = "yyyyMMdd";
    public static final String YYYY_MM_DD_WITH_DOT = "yyyy.MM.dd";
    public static final String YYYY_MM_WITH_NOT = "yyyyMM";
    public static final String YYYY_MM_WITH_CHINESE = "yyyy年MM月";


    public static Date minDate(Date date1, Date date2) {
        if (date1.before(date2)) {
            return date1;
        }
        return date2;
    }

    public static Date maxDate(Date date1, Date date2) {
        if (date1.before(date2)) {
            return date2;
        }
        return date1;
    }

    public static Integer getYear(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.get(Calendar.YEAR);
    }

    public static Integer getMonth(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int currentMonth = c.get(Calendar.MONTH) + 1;
        System.out.println("Current Month : " + currentMonth);
        return currentMonth;
    }

    public static Integer getDay(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.get(Calendar.DAY_OF_MONTH);
    }


    public static String dateToStr(Date date) {
        if (date == null) {
            return "";
        } else {
            LocalDateTime dateTime = new LocalDateTime(date);
            return dateTime.toString(DATE_PATTERN);
        }
    }

    public static Date getLastOfMonthDate(Date date) {
        org.joda.time.LocalDate localDate = new org.joda.time.LocalDate(date);
        return localDate.dayOfMonth().withMaximumValue().toDate();
    }

    public static String getLastOfMonthDateStr(Date date) {
        org.joda.time.LocalDate localDate = new org.joda.time.LocalDate(date);
        return dateToStr(localDate.dayOfMonth().withMaximumValue().toDate());
    }

    public static Date getFirstOfMonthDate(Date date) {
        org.joda.time.LocalDate localDate = new org.joda.time.LocalDate(date);
        return localDate.dayOfMonth().withMinimumValue().toDate();
    }

    public static String getFirstOfMonthDateStr(Date date) {
        org.joda.time.LocalDate localDate = new org.joda.time.LocalDate(date);
        return dateToStr(localDate.dayOfMonth().withMinimumValue().toDate());
    }

    public static Date getLastOfYearDate(Date date) {
        org.joda.time.LocalDate localDate = new org.joda.time.LocalDate(date);
        return localDate.dayOfYear().withMaximumValue().toDate();
    }

    public static Date getFirstOfYearDate(Date date) {
        org.joda.time.LocalDate localDate = new org.joda.time.LocalDate(date);
        return localDate.dayOfYear().withMinimumValue().toDate();
    }

    public static String getFirstOfDayDateStr(Date date) {
        return dateToStr(date) + " 00:00:00";
    }

    public static String getLastOfDayDateStr(Date date) {
        return dateToStr(date) + " 23:59:59";
    }

    public static String timToStr(Date date) {
        if (date == null) {
            return "";
        } else {
            LocalDateTime dateTime = new LocalDateTime(date);
            return dateTime.toString(DEFAULT_PATTERN);
        }
    }

    public static Date strToDate(String dateStr) {
        LocalDateTime dateTime = DateTimeFormat.forPattern(DATE_PATTERN).parseLocalDateTime(dateStr);
        return dateTime.toDate();
    }

    public static Date strToTime(String dateStr) {
        LocalDateTime dateTime = DateTimeFormat.forPattern(DEFAULT_PATTERN).parseLocalDateTime(dateStr);
        return dateTime.toDate();
    }

    public static String getYearMonth(Date businessTime) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM");
        return format.format(businessTime);
    }

    public static String getYearMonth(String dateStr) {
        Date date = strToDate(dateStr);
        return getYearMonth(date);
    }

    public static Date formatDate(String str, String pattern) {
        LocalDateTime dateTime = DateTimeFormat.forPattern(pattern).parseLocalDateTime(str);
        return dateTime.toDate();
    }

    public static String formatStr(Date date, String pattern) {
        LocalDateTime dateTime = new LocalDateTime(date);
        return dateTime.toString(pattern);
    }

    public static Date getYearMonthDay(Date time) {
        Calendar c = Calendar.getInstance();
        c.setTime(time);
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);
        return c.getTime();
    }

    public static Date yearMonthStrToDate(String yearMonth) {
        return formatDate(yearMonth, YYYY_MM);
    }


    public static String format(Date date, String pattern) {
        LocalDateTime dateTime = new LocalDateTime(date);
        return dateTime.toString(pattern);
    }


    public static int getDays(Date startDate, Date endDate) {
        DateTime startTime = new DateTime(startDate);
        DateTime endTime = new DateTime(endDate);
        return Days.daysBetween(startTime, endTime).getDays();
    }

    public static String getYesterday() {
        return DateUtil.dateToStr(DateUtils.addDays(new Date(), -1));
    }


    public static LocalDate toLocalDate(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    }
}
